package ide.ccf.ccproject.common;

import java.io.File;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.FileEditorInput;

/**
 * 编辑器输入监视器类
 *
 */
@SuppressWarnings("deprecation")
public class EditorInputWatcher implements IPartListener, IWindowListener, IResourceChangeListener
{
	private IEditor part;
	private long timestamp;
	private IResource resource;

	/**
	 * 构造
	 * @param part
	 */
	public EditorInputWatcher(IEditor part)
	{
		this.part = part;
		this.resource = (IResource) part.getEditorInput().getAdapter(IResource.class);
		this.part.getSite().getWorkbenchWindow().getPartService().addPartListener(this);
		PlatformUI.getWorkbench().addWindowListener(this);
		ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
		updateTimeStamp();
	}

	/**
	 * 释放
	 */
	public void dispose()
	{
		this.part.getSite().getWorkbenchWindow().getPartService().removePartListener(this);
		PlatformUI.getWorkbench().removeWindowListener(this);
		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
	}

	/**
	 * 返回文件名
	 * @return
	 */
	private String fileName()
	{
		FileEditorInput fin = (FileEditorInput) part.getEditorInput();
		if(fin  == null)
			System.out.println("fin is null");
		if(fin.getFile() == null)
			System.out.println("fin.getFile() is null");
		if(fin.getFile().getLocation() == null)
			System.out.println("fin.getFile().getLocation() is null");
		return fin.getFile().getLocation().toOSString();
	}

	/**
	 * 返回当前文件时间戳
	 * @return
	 */
	private long getCurrentTimeStamp()
	{
		return (new File(fileName())).lastModified();
	}

	/**
	 * 文件是否可读
	 * @return
	 */
	private boolean readable()
	{
		File file = new File(fileName());
		return file.exists() && file.canRead();
	}

	/**
	 * 更新文件时间戳
	 */
	public void updateTimeStamp()
	{
		if (!readable())
			timestamp = -1;
		else
			timestamp = getCurrentTimeStamp();
	}

	/**
	 * 编辑器资源变化时的IWorkbenchPart激活
	 */
	public void partActivated(IWorkbenchPart partArg)
	{
		// 时间戳大于-1意味着编辑器已经不再显示丢失的文件信息；
		// 资源检查是为了防止未保存文件从Eclipse资源系统中删除。资源删除将由资源更改侦听器处理。
		if (partArg == this.part && timestamp > -1 && (resource == null || resource.exists() || part.isDirty()))
		{
			if (!readable())
			{
				String[] buttons = { "保存", "关闭" };
				MessageDialog dialog = new MessageDialog(part.getSite().getShell(), "文件不可访问", null, "文件已更改或者不可访问。您是想要保存更改还是关闭编辑器但不保存更改？", MessageDialog.QUESTION, buttons, 0);
				if (dialog.open() == 0)
				{
					this.part.doSave(new NullProgressMonitor());
				}
				part.getSite().getShell().getDisplay().asyncExec(new Runnable()
				{
					public void run()
					{
						part.getSite().getPage().closeEditor(part, false);
					}
				});
			} 
			else
			{
				long newtimestamp = getCurrentTimeStamp();
				if (newtimestamp != timestamp)
				{
					if (MessageDialog.openQuestion(part.getSite().getShell(), "文件已更改", "已在文件系统上更改了文件。要用这些更改替换编辑器内容吗？"))
					{
						this.part.reload();
					}
				}
			}
			updateTimeStamp();
		}
	}

	
	public void partBroughtToTop(IWorkbenchPart part)
	{
	}

	public void partClosed(IWorkbenchPart part)
	{
	}

	public void partDeactivated(IWorkbenchPart part)
	{
	}

	public void partOpened(IWorkbenchPart part)
	{
	}

	/**
	 * 窗口激活
	 */
	public void windowActivated(IWorkbenchWindow window)
	{
		if (window == part.getEditorSite().getWorkbenchWindow())
		{
			// 否则对话框可能无法显示：
			window.getShell().getDisplay().asyncExec(new Runnable()
			{
				public void run()
				{
					partActivated(part);
				}
			});
		}
	}

	/**
	 * 窗口关闭
	 */
	public void windowClosed(IWorkbenchWindow window)
	{
	}

	public void windowDeactivated(IWorkbenchWindow window)
	{
	}

	public void windowOpened(IWorkbenchWindow window)
	{
	}

	/**
	 * 资源更改
	 */
	public void resourceChanged(IResourceChangeEvent event)
	{
		handleResourceDelta(event.getDelta());
	}

	/**
	 * 创建丢失文件显示信息
	 * @param parent
	 * @param fileName
	 * @return
	 */
	public static Control createMissingFileInfo(Composite parent, String fileName)
	{
/*		parent.setLayout(new FillLayout(SWT.VERTICAL));
		InfoForm info = new InfoForm(parent);
		
		info.setBannerText("");
		info.setHeaderText("");
		info.setInfo("文件" + fileName + "不存在或者不可读。");
		
		return info.getControl();*/
		return null;
	}

	/**
	 * 处理资源变动
	 * @param delta
	 * @return
	 */
	private boolean handleResourceDelta(IResourceDelta delta)
	{
		// 会有一些不属于资源变动的事件
		if (delta == null)
			return false;
		
		if (delta.getKind() == IResourceDelta.REMOVED)
		{
			if (delta.getResource().equals(resource))
			{
				part.getSite().getShell().getDisplay().syncExec(new Runnable()
				{
					public void run()
					{
						part.getSite().getPage().closeEditor(part, false);
					}
				});
				return true;
			}
		}

		IResourceDelta deltas[] = delta.getAffectedChildren();
		for (int i = 0; deltas != null && i < deltas.length; ++i)
		{
			if (handleResourceDelta(deltas[i]))
				return true;
		}
		return false;
	}
}
